Borland Online And The Cobb Group Present:


June, 1995 - Vol. 2 No. 6

Showing splash screens in an OWL application

Much of what you'll remember about an application relates to the impression it makes on you the first time you run it. One of the hallmarks of a professional application is the splash screen, the initial window that identifies the application and its developer. The Borland C++ Integrated Development Environment (IDE) displays such a screen when you launch it, as shown in Figure A.


Figure A - The Borland C++ IDE displays a modest splash screen when you launch it.

Unfortunately, if you're not careful, creating a splash screen for your ObjectWindows Library (OWL) 2.0 or 2.5 application can become very complex. In this article, we'll show how you can avoid confusion by creating a simple C++ class that manages your individual appli-cation's splash screen display.

Making a splash

While nearly every commercial application has a splash screen, some of these screens are better than others. The good ones share several characteristics: They're unobtrusive, attractive, and informative.

By unobtrusive, we mean that the splash screen doesn't call undue attention to itself. For example, most splash screens don't force the user to click a button to dismiss the screen. Frequently, you can click anywhere, with either mouse button, and the splash screen will disappear. Another popular style of splash screen disappears automatically after a few seconds pass.

Attractive splash screens take advantage of good design features. Adding three-dimensional ridges, recessed or embossed rectangular regions, or styled text can make a big difference in the appearance of a simple splash screen. However, you can easily add too many decorations to the splash screen, thereby interfering with its ability to communicate the information.

Finally, a splash screen should identify the application, the software version, and the development company. If you have a corporate logo or trademark, a splash screen is an ideal place to display it, reinforcing the image in the customer's mind. (After all, they'll probably see the splash screen each time they launch the application.) Unfortunately, we can't provide code that guarantees attractive and informative splash screens. Instead, we'll provide you with a splash screen class that's unobtrusive, and we'll let you choose the content.

We'll derive the splash screen class from the TDialog class. This will allow you to create your splash screen entirely as a dialog box resource. (If you want to create a truly decorative splash screen, see Resource Workshop tip - Displaying bitmaps in dialog boxes.)

To allow the user to dismiss the splash screen easily, we'll want to respond to the WM_LBUTTONDOWN message and the WM_RBUTTONDOWN message by calling the TWindow::CloseWindow( ) member function. This way, no matter which button the user presses, the splash screen will disappear.

However, if the splash screen responded to mouse clicks in the usual way, the user would have to click the mouse button within the window region of the splash screen. Instead, we can use the SetCapture( ) and ReleaseCapture( ) member functions from the TWindow class to capture all mouse events­­even those outside the splash screen itself­­while the splash screen is still visible.

If the user doesn't click the mouse, the application should close the splash screen after a certain amount of time passes. To provide this behavior, we'll tell Windows to create a timer that issues a WM_TIMER message five seconds after the splash screen appears. Then, we'll respond to the WM_TIMER message by calling the TWindow::CloseWindow( ) member function.

Taking the plunge

To see how you can create a splash screen for an OWL application, let's build a simple example. To begin, launch the IDE.

When the IDE's main window appears, choose New Project... from the Project menu. In the New Project dialog box, enter \SPLASH\SPLASH.IDE in the Project Path And Name entry field, select Application [.exe] from the Target Type list box, select the OWL and BWCC check boxes in the Standard Libraries section, and click OK.

When the SPLASH.IDE project window appears, right-click on splash [.def] and choose Delete Node from the pop-up menu. When the IDE prompts you to confirm deleting this node, click Yes.

Double-click on the splash [.cpp] node. When the editing window for this file appears, enter the code from Listing A.


Listing A: SPLASH.CPP

#include <owl\owlpch.h>

class TSplashDialog : public TDialog
{
 public:
  TSplashDialog(TWindow* wnd,
		TResId res = 1,
		TModule* mod = 0) :
    TDialog(wnd, res, mod)
  {}

  ~TSplashDialog( )
  { KillTimer(1);
    ReleaseCapture( );
    Destroy( ); }

 protected:
  void SetupWindow( );

  void EvLButtonDown(UINT, TPoint&)
  { CloseWindow( ); }

  void EvRButtonDown(UINT, TPoint&)
  { CloseWindow( ); }

  void EvTimer(UINT id)
  { TDialog::EvTimer(id);
    CloseWindow( ); }

DECLARE_RESPONSE_TABLE(TSplashDialog);
};

DEFINE_RESPONSE_TABLE1(TSplashDialog, TDialog)
  EV_WM_TIMER,
  EV_WM_LBUTTONDOWN,
  EV_WM_RBUTTONDOWN,
END_RESPONSE_TABLE;

void TSplashDialog::SetupWindow( )
{
  TDialog::SetupWindow( );
  RECT DesktopRect;
  ::GetWindowRect(GetDesktopWindow( ), 
      &DesktopRect);

  SetWindowPos(HWND_TOPMOST,
    (DesktopRect.right -
      GetWindowRect( ).Width( )) / 2,
    (DesktopRect.bottom -
      GetWindowRect( ).Height( )) / 2,
    0,0, SWP_NOSIZE);

  SetTimer(1, 5000, 0);
  SetCapture( );
}


class TSplashApp : public TApplication
{
  public:
    TSplashApp( ){}
    void InitMainWindow( )
    { SetMainWindow(new TFrameWindow(0, 
        "Splash", 0));
      TSplashDialog* splash =
	  new TSplashDialog(GetMainWindow( ));
      splash->Create( ); }
};

int OwlMain(int, char* [])
{ 
  return TSplashApp( ).Run( ); 
}

When you finish entering this code, choose Save from the File menu. Next, right-click on the splash [.rc] node and choose Text Edit from the View submenu. When the editing window for this file appears, enter the resource code from Listing B. When you finish entering the resource code, choose Save from the File menu. Double-click on the SPLASH.RC file window's System menu icon to close the window.


Listing B: SPLASH.RC

1 DIALOG 0, 0, 161, 114
STYLE WS_POPUP | WS_VISIBLE | WS_BORDER
FONT 8, "MS Sans Serif"     
{
 CONTROL "",
  -1, "BorShade",
  BSS_RGROUP | BSS_CAPTION | BSS_LEFT |
  WS_CHILD | WS_VISIBLE | WS_GROUP,
  0, 0, 161, 114
 CONTROL "Splash - Version 1.0",
  -1, "BorStatic",
  SS_CENTER | WS_CHILD | WS_VISIBLE | WS_GROUP,
  15, 20, 130, 11
 CONTROL "",
  -1, "BorShade",
  BSS_HDIP | BSS_LEFT | WS_CHILD | WS_VISIBLE,
  6, 52, 148, 1
 CONTROL "Copyright c 1995 - TylerSoft",
  -1, "BorStatic",
  SS_CENTER | WS_CHILD | WS_VISIBLE | WS_GROUP,
  15, 73, 130, 11
} 

Now let's review the code that appears in SPLASH.CPP. First, we'll examine the TSplashDialog class itself.

The constructor TSplashDialog( ) doesn't do anything unusual except provide a default value for the resource identifier res. Since we use the same identifier in the resource description file, this class will load the correct dialog box by default.

In the destructor ~TSplashDialog( ), you'll notice we do three things. First, we call the KillTimer( ) member function from the TWindow class and pass to it the timer identification value that appears later in the SetupWindow( ) member function. When you call this function, the TWindow class, in turn, calls the Windows KillTimer( ) function to delete the appropriate timer.

Second, the destructor calls the TWindow::ReleaseCapture( ) member function. This function disables the routing of mouse-button messages to the splash- screen window and allows Windows to process the messages normally.

Finally, the destructor calls the Destroy( ) member function to clean up all of the corresponding Windows structures that a TSplashDialog object uses when it appears. The remainder of the TSplashDialog class consists of standard message response functions for the left and right mouse-down messages, a response function for the WM_TIMER message, and the DECLARE_RESPONSE_TABLE macro.

Next, you'll notice the response table definition macros. (If you're not familiar with the OWL message response tables, see "Responding to Standard Messages with ObjectWindows 2.0," from the March 1994 issue of Borland C++ Developer's Journal.)

At the heart of the TSplashDialog class is the SetupWindow( ) member function. The OWL source code calls this function just before displaying the splash screen's window. The first part of the function calculates the appropriate coordinates for centering the splash screen. Near the end of the function, it calls the member function TWindow::SetTimer( ) to initialize a five-second Windows timer and to call TWindow::SetCapture( ) to force all left-button or right-button mouse messages to appear as if the messages apply to the splash-screen window.

Near the end of the SPLASH.CPP file, we declare a new class, TSplashApp. This class doesn't do anything unusual except display the splash screen from within the InitMainWindow( ) member function. Now, let's build the application to see how the splash screen performs.

Going for a dip

To build and run the application, choose Run from the Debug menu. When the compiler finishes building the application, you'll see the application's main window and the splash screen appear at about the same time. The splash screen will appear in the center of the screen, as shown in Figure B.

Figure B - The splash screen will appear in the center of the screen when you launch the SPLASH.EXE application.

Wait five seconds, and the splash screen will disappear, just as you would expect. Double-click on the SPLASH application's System menu icon. If you want to test the splash screen's response when you click with either mouse button, rerun the application and click with either button, anywhere on the screen.

By the way, since this example uses controls that are part of the Borland Windows Custom Controls library (BWCC.DLL), you'll need to distribute that file along with your application. Before the user runs the program, you'll need to make sure the BWCC.DLL file is in the user's \WINDOWS\SYSTEM directory.

Conclusion

Splash screens are a very visible component of several commercial applications. By using the technique we've shown here, you can quickly create a splash screen that will appear each time a user launches your application.

Return to the Borland C++ Developer's Journal index

Subscribe to the Borland C++ Developer's Journal


Copyright (c) 1996 The Cobb Group, a division of Ziff-Davis Publishing Company. All rights reserved. Reproduction in whole or in part in any form or medium without express written permission of Ziff-Davis Publishing Company is prohibited. The Cobb Group and The Cobb Group logo are trademarks of Ziff-Davis Publishing Company.